#!/usr/bin/env python
# Copyright (C) 2007 Samuel Abels, http://debain.org
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2, as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
import sys, os, tempfile
sys.path.insert(0, 'src')
from Text2Xml.FooLib       import OptionParser
from Text2Xml.Parser       import Parser
from Text2Xml.CGenerator   import CGenerator
from Text2Xml.XmlGenerator import XmlGenerator

__version__ = '0.0.1'

def usage():
    print "text2xml %s" % __version__
    print "Copyright (C) 2007 by Samuel Abels <http://debain.org>."
    print "Syntax: text2xml -c syntax_file [-o module_file]"
    print "        text2xml -e syntax_file [-o executable_file]"
    print "        text2xml -s syntax_file [-o xml_file] input_file [input_file ...]"
    print "  -c, --compile FILE"
    print "                 Reads the syntax from the given file and compiles"
    print "                 it. The resulting syntax module is written to"
    print "                 FILENAME.so, where FILENAME is the basename of"
    print "                 the given input file."
    print "  -d, --debug LEVEL"
    print "                 Set the debug level. The default level is 0 (no"
    print "                 debugging)."
    print "  -e, --executable FILE"
    print "                 Like -c, but the resulting file is an executable"
    print "                 binary, not a .so module. The resulting executable"
    print "                 is written to FILENAME.parser, where FILENAME is"
    print "                 the basename of the given input file."
    print "  -s, --syntax FILE"
    print "                 Uses the given syntax to parse the input file."
    print "                 FILE may be either a .def file containing the"
    print "                 syntax description, or a compiled syntax module."
    print "                 The resulting XML is written to FILENAME.xml,"
    print "                 where FILENAME is the basename of the input file."
    print "  -o, --output FILE"
    print "                 When given with -c, this specifies the name of"
    print "                 the resulting module file."
    print "                 When given with -e, this specifies the name of"
    print "                 the resulting executable file."
    print "                 When given with -s, this specifies the name of"
    print "                 the resulting XML file."
    print "      --version  Prints the version number."
    print "  -h, --help     Prints this help."

# Define default options.
default_options = [
  ('compile=',    'c:', None),
  ('debug=',      'd:', 0),
  ('executable=', 'e:', None),
  ('syntax=',     's:', None),
  ('output=',     'o:', None),
  ('version',     None, False),
  ('help',        'h',  False)
]

# Parse options.
try:
    options, args = OptionParser.parse_options(sys.argv, default_options)
except:
    usage()
    sys.exit(1)

# Show the help, if requested.
if options['help']:
    usage()
    sys.exit()

# Show the version number, if requested.
if options['version']:
    print "text2xml %s" % __version__
    sys.exit()

# Check command line syntax.
if [options['compile'], options['executable'], options['syntax']].count(None) < 2:
    print "Error: More than one of conflicting switches -c, -e, and -s."
    sys.exit(1)
elif options['compile']:
    if len(args) > 0:
        print "Error: Can't specify an input file with -c switch."
        sys.exit(1)
elif options['executable']:
    if len(args) > 0:
        print "Error: Can't specify an input file with -e switch."
        sys.exit(1)
elif options['syntax']:
    if len(args) == 0:
        print "Error: No input files given."
        sys.exit(1)
else:
    print "Error: Required switch -c, -e, or -s missing."
    sys.exit(1)

# Run.
compile_file  = None
compiler_args = {}
if options['compile']:
    if not os.path.exists(options['compile']):
        print "Error: No such file: %s" % options['compile']
        sys.exit(1)
    compile_file = options['compile']
    basename_out = os.path.basename(options['compile'])
    default_out  = os.path.splitext(basename_out)[0] + '.so'
    outfile      = options.get('output') or default_out
    compiler_args['shared_lib'] = outfile

if options['executable']:
    if not os.path.exists(options['executable']):
        print "Error: No such file: %s" % options['executable']
        sys.exit(1)
    compile_file = options['executable']
    basename_out = os.path.basename(options['executable'])
    default_out  = os.path.splitext(basename_out)[0] + '.parser'
    outfile      = options.get('output') or default_out
    compiler_args['executable'] = outfile

if options['syntax'] and os.path.splitext(options['syntax'])[1] == '.def':
    compile_file = options['syntax']
    tmpfile      = tempfile.NamedTemporaryFile()
    compiler_args['shared_lib'] = tmpfile.name
    options['syntax'] = compiler_args['shared_lib']

if compile_file:
    print "Parsing the syntax...",
    parser     = Parser(debug = 0)
    parse_tree = parser.parse_file(compile_file)
    print "done."

    print "Compiling the syntax...",
    generator = CGenerator(debug_level = options['debug'])
    generator.compile(parse_tree, **compiler_args)
    print "done."

if options['syntax']:
    if not os.path.exists(options['syntax']):
        print "Error: No such file: %s" % options['syntax']
        sys.exit(1)

    generator = XmlGenerator(options['syntax'], debug = options['debug'])
    for file in args:
        default_out = os.path.splitext(os.path.basename(file))[0] + '.xml'
        xml_out     = options.get('output', default_out) or default_out

        if options['debug'] > 0:
            print "Parsing %s to %s..." % (file, xml_out),
        try:
            xml = generator.convert(file)
        except:
            print "In %s:" % file
            raise
        if options['debug'] > 0:
            print xml
        fp  = open(xml_out, 'w')
        fp.write(xml)
        fp.close()
        if options['debug'] > 0:
            print "done."
